<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    class EventEmitter {
      constructor() {
        this.event = {}
      }
      publish(eventName, ...args){
        if(this.event[eventName]){
          this.event[eventName].forEach((cb) => cb.apply(this, args))
        }
      }
      subscribe(eventName, callback){
        if(this.event[eventName]){
          this.event[eventName].push(callback)
        } else {
          this.event[eventName] = [callback]
        }
      }
      unsubscribe(eventName, callback){
        if(this.event[eventName]) {
          this.event[eventName].filter(cb => cb !== callback)
        }
      }
    }
    /* 防抖 */
    function debounce(fn, delay) {
      let timer = null
      return function(...args){
        if(timer){
          clearInterval(timer)
        }
        timer = setTimeout(() => {
          fn.apply(this, args)
        },delay)
      }
    }

    /* 节流 */
    function throttle(fn, delay){
      let pre = 0
      return function(...args){
        let now = new Date()
        if(now - pre >= delay){
          pre = now
          fn.apply(this, args)
        }
      }
    }
    function throttle(fn, delay) {
      let timer = null
      return function(...args){
        if(!timer){
          timer = setTimeout(() => {
            fn.apply(this, args)
            timer = null
          },delay)
        }
      }
    }

    function myNew(fn, ...args){
      const obj = {}
      obj.__proto__ = fn.prototype
      let res = fn.apply(obj, args)
      return res && typeof res === "object" ? res : obj
    }

    Function.prototype.myBind = function(ctx, ...args) {
      if(typeof this !== "function") {
        throw new Error('TYPE ERROR')
      }
      const fn = this
      return function(...subArgs) {
        const allArgs = [...args, ...subArgs]
        if (new.target){
          return new fn(...allArgs)
        } else {
          return fn.apply(ctx, allArgs)
        }
      }
    }
    Function.prototype.myCall = function(ctx, ...args) {
      ctx = ctx === null || ctx === undefined ? globalThis : Object(ctx)
      const fn = this
      const key = Symbol()
      ctx[key] = fn
      const res = ctx[key](...args)
      delete ctx[key]
      return res
    }
  </script>
</body>
</html>